#include "N2MemoryDrawer.h"

N1NAME_DEF(N2MemoryDrawer)

N2MemoryDrawer::N2MemoryDrawer() : m_pData(NULL), m_nByteInRow(0), m_nSize(0), 
                       m_nWidth(0), m_nHeight(0), m_nBPP(0), m_palette(NULL)
{
    m_brush = new N2Brush(N2Color::whiteColor());
}

N2MemoryDrawer::~N2MemoryDrawer()
{
    delete []m_pData;
    if(m_palette)
    {
        m_palette->release();
    }
    m_brush->retain();
}


N2Size N2MemoryDrawer::getSize() const 
{
    return N2Size(m_nWidth, m_nHeight);
}

uint32 N2MemoryDrawer::getBitsPerPixel() const 
{
    return m_nBPP;
}

void N2MemoryDrawer::setWorldTransform(const N2WorldTransform &wt)
{
    m_wt = wt;
}

N2WorldTransform N2MemoryDrawer::getWorldTransform() const 
{
    return m_wt;
}

void     N2MemoryDrawer::setColor(const N2Color &color)
{
}

N2Color  N2MemoryDrawer::getColor() const 
{
    return N2Color::whiteColor();
}

void     N2MemoryDrawer::setBrush(N2Brush *brush)
{
    if(m_brush==brush) return;

    m_brush->release();
    m_brush = brush;
    m_brush->retain();
}

N2Brush* N2MemoryDrawer::getBrush() const 
{
    return m_brush;
}

uint32 N2MemoryDrawer::getPixel(uint32 x, uint32 y) const 
{
    uint32 ret = 0;

    m_wt.modify(x, y);

    if(x>=m_nWidth || y>=m_nHeight) return 0;

    BYTE *pRow = (BYTE*)m_pData + m_nByteInRow * y;

    switch(m_nBPP) 
    {
        case 1:
            ret = (*(pRow + x/8) >> x%8) & 1;
            if(ret) ret = RGB(255,255,255);
            break;
        case 4:
            if(x&1)
                ret = (*(pRow + x/2) & 0xF);
            else
                ret = (*(pRow + x/2) >> 4);
            break;
        case 8:
            ret = *(pRow + x);
            break;
        case 16:
            ret = *((uint16*)pRow + x);
            break;
        case 24:
            pRow += x*3;
            ret = (*pRow++) | (*pRow++)<<8  | (*pRow)<<16;
            break;
        case 32:
            ret = *((uint32*)pRow + x);
            break;
    }
    return ret;
}

void   N2MemoryDrawer::setPixel(uint32 x, uint32 y)
{
    m_wt.modify(x, y);

}

void   N2MemoryDrawer::drawVertLine(uint32 x, uint32 y1, uint32 y2)
{
}

void   N2MemoryDrawer::drawHorzLine(uint32 y, uint32 x1, uint32 x2)
{
}

void   N2MemoryDrawer::fillRect(const N2Rect &rect)
{
}

N2Color  N2MemoryDrawer::getPoint(const N2Point &point) const 
{
    uint32 ret = getPixel(point.x, point.y);

    switch(m_nBPP) 
    {
        case 1:
            if(ret) return N2Color::whiteColor();
            break;
        case 4:
        case 8:
            return m_palette->getColor(ret);
            return m_palette->getColor(ret);
        case 16:
            return N2Color(ret);
        case 24:
        case 32:
            return N2Color(ret);
    }

    return N2Color::blackColor();
}

void N2MemoryDrawer::drawPoint(const N2Point &point)
{
    setPixel(point.x, point.y);
}

void N2MemoryDrawer::drawLine(const N2Point &from, const N2Point &to)
{
}

void N2MemoryDrawer::drawRect(const N2Rect &rect)
{
}

void N2MemoryDrawer::drawShape(const N2Point *points, uint32 count)
{
}

bool N2MemoryDrawer::createInMemory(uint16 bitsPerPixel, uint32 width, uint32 height)
{
    if(m_pData) return false;
    if(!(bitsPerPixel==1 || bitsPerPixel==4 || bitsPerPixel==8 || 
        bitsPerPixel==16 || bitsPerPixel==24 || bitsPerPixel==32)) return false;

    m_nByteInRow = ( width * bitsPerPixel + 31) / 32 * 4;
    m_nSize = m_nByteInRow * height;
    m_pData = NULL;
    try {  m_pData = new char[ m_nSize ]; }
    catch(...) {}
    if(!m_pData) return FALSE;
    memset(m_pData, 0xFF, m_nSize);
    m_nWidth = width;
    m_nHeight = height;
    m_nBPP = bitsPerPixel;
    return false;
}
